the inefficent loop
This loop runs through the netcdf files and then looks for which rows in data_aea it should extract the value to point from, and at what depth (netcDF layer)
Start with 2007_10 data
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/env/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 2007 # a variable for the observation year
mth <- 10 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
[1] "2007_10_chl.nc"
ok now create the first lot of random for 2007_10
testbk100001999 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200001999 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300001999 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500001999 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000001999 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900001999 <- test_back_df[sample(nrow(test_back_df), 190000), ]
plot each variable against the different no of background points
ggplot(test10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/ssh_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/mlp_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Try again for another month - say 1999 02 AND again 2014 06
This time extract the values for all points and then subset
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 1999 # a variable for the observation year
mth <- 02 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
[1] "1999_02_chl.nc"
[1] "1999_02_mlp.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_o2.nc"
[1] "1999_02_salinity.nc"
[1] "1999_02_ssh.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_temp.nc"
write.csv(testbglistsp, "../data/env/background_point_check/1999_02/testbglistoutput.csv", row.names = FALSE)
#test_back_df <- as.data.frame(testbk100000sp)
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.277501 hours
ok now create the first lot of random for 1999_02
testbk100001999 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200001999 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300001999 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500001999 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000001999 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900001999 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100001999, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_ssh_back.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_mlp.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_temp_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_temp_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_salinity_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_salinity_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_chl_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_chl_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_o2_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_o2_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
And now 2014_06
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.455486 hours
ok now create the first lot of random for 2014_06
testbk100002014 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200002014 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300002014 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500002014 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000002014 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900002014 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100002014, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_ssh.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_mlp.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
LS0tDQp0aXRsZTogImJhY2tncm91bmQgcG9pbnRzIC0gaXMgbW9yZSBiZXR0ZXI/Ig0KYXV0aG9yOiAiU2FtYW50aGEgQW5kcmV3cyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KIyBPdmVydmlldw0KcXVpY2sgdGVzdCB0byBzZWUgd2hhdCBoYXBwZW5zIHRvIGRpc3RyaWJ1dGlvbiBvZiBlbnYuIHZhcmlhYmxlcyBpZiBhZGQgbW9yZSBiYWNrZ3JvdW5kIHBvaW50cyAoaXMgMTBrIGVub3VnaCBvciBkbyBJIG5lZWQgbW9yZSkNCg0KQSBub3RlIHRvIGFueW9uZSB3aG8gbWlnaHQgaGFwcGVuIHRvIHN0dW1ibGUgYWNyb3NzIHRoaXMuLi4gSSBhbSBhIGJlZ2lubmVyIGluIFIgYW5kIGhhdmUgaGFkIG5vIGV4cG9zdXJlIHRvIHNpbWlsYXIgbGFuZ3VhZ2VzLiBJIGRvbid0IGtub3cgd2hhdCBJJ20gZG9pbmcuIFRoZSBjb2RlIGhlcmVpbiBpcyB1bmxpa2VseSB0byBiZSBlbGVnYW50IGFuZCB0aGVyZSBhcmUgcHJvYmFibHkgbW9yZSBlZmZpY2llbnQgd2F5cyBvZiBydW5uaW5nIHRoZSBjb2RlLg0KDQpCdWlsdCB3aXRoICdyIGdldFJ2ZXJzaW9uKCknLg0KDQojIFBhY2thZ2UgZGVwZW5kZW5jaWVzDQpZb3UgY2FuIGxvYWQgdGhlbSB1c2luZyB0aGUgZm9sbG93aW5nIGNvZGUgd2hpY2ggdXNlcyBhIGZ1bmN0aW9uIGNhbGxlZCBbaXBha10oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vc3RldmVud29ydGhpbmd0b24vMzE3ODE2MykuIA0KTm90ZSB0aGlzIGZ1bmN0aW9uIGNoZWNrcyB0byBzZWUgaWYgdGhlIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgZmlyc3QuDQpUaGUgImluY2x1ZGU9RkFMU0UiIHN1cHJlc3NlcyB0aGUgcGFja2FnZSBpbnN0YWxsYXRpb24gdGV4dCBhcHBlYXJpbmcgaW4gdGhlIGRvY3VtZW50Li4uDQpgYGB7ciBwcmUtaW5zdGFsbCBwYWNrYWdlcywgaW5jbHVkZT1GQUxTRX0NCnBhY2thZ2VzIDwtIGMoIm5jZGY0IiwgInJhc3RlciIsICJnZ3Bsb3QyIiwgInBsb3RseSIpIA0Kc291cmNlKCIuLi9zcmMvaXBhay5SIikNCmlwYWsocGFja2FnZXMpDQpgYGANCg0KbG9hZCB0aGUgcmF3IGJhY2tncm91bmQuY3N2IGZpbGUgd2l0aCBhbGwgcG9pbnRzIHRvIHJhbmRvbWx5IGV4dHJhY3QgcG9pbnRzIGZyb20gKC4uL291dHB1dC9lbnYvdW5pcXVlX2NlbGxfY2VudHJvaWRfbG9ubGF0X25hZm8yX2RlcHRoLmNzdikNCg0KYGBge3J9DQp0ZXN0YmdsaXN0IDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvZW52L3VuaXF1ZV9jZWxsX2NlbnRyb2lkX2xvbmxhdF9uYWZvMl9kZXB0aC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KaGVhZCh0ZXN0YmdsaXN0KQ0KYGBgDQoNCmBgYHtyfQ0KYmFja29ic25vIDwtIG5yb3codGVzdGJnbGlzdCkNCmJhY2tvYnNubw0KYGBgDQoNCg0KDQojIHRoZSBpbmVmZmljZW50IGxvb3ANCg0KDQoNClRoaXMgbG9vcCBydW5zIHRocm91Z2ggdGhlIG5ldGNkZiBmaWxlcyBhbmQgdGhlbiBsb29rcyBmb3Igd2hpY2ggcm93cyBpbiBkYXRhX2FlYSBpdCBzaG91bGQgZXh0cmFjdCB0aGUgdmFsdWUgdG8gcG9pbnQgZnJvbSwgYW5kIGF0IHdoYXQgZGVwdGggKG5ldGNERiBsYXllcikNCg0KU3RhcnQgd2l0aCAyMDA3XzEwIGRhdGENCg0KYGBge3J9DQpzdHJ0IDwtIFN5cy50aW1lKCkgI2dldCB0aGUgc3RhcnQgdGltZQ0KDQp4eSA8LSB0ZXN0YmdsaXN0WyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmdsaXN0c3AgPC0gU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSB4eSwgZGF0YSA9IHRlc3RiZ2xpc3QsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj1hZWEgK2xhdF8xPTUwICtsYXRfMj03MCArbGF0XzA9NDAgK2xvbl8wPS02MCAreF8wPTAgK3lfMD0wICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPW0gK25vX2RlZnMiKSkgIyBUaGUgQ1JTIGlzIHVzZWQgaGVyZSBpcyBmb3IgdGhlIGFsYmVycyBlcXVhbCBhcmVhIHByb2plY3Rpb24uDQoNCg0KbmV0Y2RmX2xpc3QgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IEZBTFNFKSAjZmFsc2UgbWVhbnMgdGhlIHBhdGggaXMgbm90IGluY2x1ZGVkDQphZWEgPC0gcmFzdGVyKCIuLi9vdXRwdXQvZW52L2FlYS50aWYiKSANCnlyIDwtIDIwMDcgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIHllYXINCm10aCA8LSAxMCAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gbW9udGgNCg0KZm9yIChpIGluIDE6bm9fbmV0Y2RmKSB7ICANCiAgcHJpbnQobmV0Y2RmX25hbWVbaV0pICN0aGlzIGp1c3QgcHJpbnRzIHRoZSBuYW1lIG9mIHRoZSBuZXRDREYgUiBpcyB3b3JraW5nIG9uZQ0KICBicmt5ciA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMSkpICMgZXh0cmFjdGluZyB0aGUgZmlyc3QgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgeWVhcikNCiAgYnJrbXRoIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAyKSkgIyBleHRyYWN0aW5nIHRoZSBzZWNvbmQgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgbW9udGgpDQogIGJya3ZhciA8LSAoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAzKSkgIyBleHRyYWN0aW5nIHRoZSB0aGlyZCBwYXJ0IG9mIHRoZSBuZXRjZGYgKGluYy5uYykNCiAgdGVtcF9icmljayA8LSBicmljayhuZXRjZGZfbGlzdFtpXSwgbHZhciA9IDQpDQogIHRlbXBfYnJpY2sgPC0gcHJvamVjdFJhc3Rlcih0ZW1wX2JyaWNrLCBhZWEpIA0KICAgIGZvciAoaiBpbiAxOm5yb3codGVzdGJnbGlzdHNwKSkgeyAgDQogICAgICBkZSA8LSB0ZXN0YmdsaXN0c3AkZGVwdGhsYXllcm5vW1tqXV0gICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIGRlcHRoIGxheWVyDQogICAgICAgICAgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAidGVtcC5uYyIpew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic2FsaW5pdHkubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAiY2hsLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm8yLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm1scC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG1scF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic3NoLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc3NoX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgIA0KICAgICAgICAgIH0NCiAgICAgDQogICAgfQ0KfQ0Kd3JpdGUuY3N2KHRlc3RiZ2xpc3RzcCwgIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX2FsbGJhY2tncm91bmRwb2ludHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp0ZXN0X2JhY2tfZGYgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0YmdsaXN0c3ApDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCg0Kb2sgbm93IGNyZWF0ZSB0aGUgZmlyc3QgbG90IG9mIHJhbmRvbSBmb3IgMjAwN18xMA0KDQpgYGB7cn0NCnRlc3RiazEwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAyMDAwMCksIF0gIA0KdGVzdGJrMzAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAzMDAwMCksIF0gIA0KdGVzdGJrNTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCA1MDAwMCksIF0gIA0KdGVzdGJrMTAwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxOTAwMDApLCBdICANCmBgYA0KDQoNCg0KcGxvdCBlYWNoIHZhcmlhYmxlIGFnYWluc3QgdGhlIGRpZmZlcmVudCBubyBvZiBiYWNrZ3JvdW5kIHBvaW50cw0KDQoNCg0KYGBge3J9DQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHNzaF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3NzaF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG1scF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX21scF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF90ZW1wX3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3RlbXBfZGVwdGhfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3NhbGluaXR5X3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9zYWxpbml0eV9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX2NobF9zdXJmYWNlX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gY2hsX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX2NobF9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG8yX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfbzJfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX28yX2RlcHRoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KVHJ5IGFnYWluIGZvciBhbm90aGVyIG1vbnRoIC0gc2F5IDE5OTkgMDIgQU5EIGFnYWluIDIwMTQgMDYNCg0KVGhpcyB0aW1lIGV4dHJhY3QgdGhlIHZhbHVlcyBmb3IgYWxsIHBvaW50cyBhbmQgdGhlbiBzdWJzZXQNCg0KYGBge3J9DQpzdHJ0IDwtIFN5cy50aW1lKCkgI2dldCB0aGUgc3RhcnQgdGltZQ0KDQp4eSA8LSB0ZXN0YmdsaXN0WyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmdsaXN0c3AgPC0gU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSB4eSwgZGF0YSA9IHRlc3RiZ2xpc3QsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj1hZWEgK2xhdF8xPTUwICtsYXRfMj03MCArbGF0XzA9NDAgK2xvbl8wPS02MCAreF8wPTAgK3lfMD0wICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPW0gK25vX2RlZnMiKSkgIyBUaGUgQ1JTIGlzIHVzZWQgaGVyZSBpcyBmb3IgdGhlIGFsYmVycyBlcXVhbCBhcmVhIHByb2plY3Rpb24uDQoNCg0KbmV0Y2RmX2xpc3QgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9lbnYvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IEZBTFNFKSAjZmFsc2UgbWVhbnMgdGhlIHBhdGggaXMgbm90IGluY2x1ZGVkDQphZWEgPC0gcmFzdGVyKCIuLi9vdXRwdXQvZW52L2FlYS50aWYiKSANCnlyIDwtIDE5OTkgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIHllYXINCm10aCA8LSAwMiAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gbW9udGgNCg0KZm9yIChpIGluIDE6bm9fbmV0Y2RmKSB7ICANCiAgcHJpbnQobmV0Y2RmX25hbWVbaV0pICN0aGlzIGp1c3QgcHJpbnRzIHRoZSBuYW1lIG9mIHRoZSBuZXRDREYgUiBpcyB3b3JraW5nIG9uZQ0KICBicmt5ciA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMSkpICMgZXh0cmFjdGluZyB0aGUgZmlyc3QgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgeWVhcikNCiAgYnJrbXRoIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAyKSkgIyBleHRyYWN0aW5nIHRoZSBzZWNvbmQgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgbW9udGgpDQogIGJya3ZhciA8LSAoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAzKSkgIyBleHRyYWN0aW5nIHRoZSB0aGlyZCBwYXJ0IG9mIHRoZSBuZXRjZGYgKGluYy5uYykNCiAgdGVtcF9icmljayA8LSBicmljayhuZXRjZGZfbGlzdFtpXSwgbHZhciA9IDQpDQogIHRlbXBfYnJpY2sgPC0gcHJvamVjdFJhc3Rlcih0ZW1wX2JyaWNrLCBhZWEpIA0KICAgIGZvciAoaiBpbiAxOm5yb3codGVzdGJnbGlzdHNwKSkgeyAgDQogICAgICBkZSA8LSB0ZXN0YmdsaXN0c3AkZGVwdGhsYXllcm5vW1tqXV0gICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIGRlcHRoIGxheWVyDQogICAgICAgICAgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAidGVtcC5uYyIpew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic2FsaW5pdHkubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAiY2hsLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm8yLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm1scC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG1scF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic3NoLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc3NoX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgIA0KICAgICAgICAgIH0NCiAgICAgDQogICAgfQ0KfQ0Kd3JpdGUuY3N2KHRlc3RiZ2xpc3RzcCwgIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX2FsbGJhY2tncm91bmRwb2ludHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp0ZXN0X2JhY2tfZGYgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0YmdsaXN0c3ApDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCg0Kb2sgbm93IGNyZWF0ZSB0aGUgZmlyc3QgbG90IG9mIHJhbmRvbSBmb3IgMTk5OV8wMg0KDQpgYGB7cn0NCnRlc3RiazEwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAyMDAwMCksIF0gIA0KdGVzdGJrMzAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAzMDAwMCksIF0gIA0KdGVzdGJrNTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCA1MDAwMCksIF0gIA0KdGVzdGJrMTAwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxOTAwMDApLCBdICANCmBgYA0KDQphbmQgcGxvdA0KDQoNCmBgYHtyfQ0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBzc2hfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8xOTk5MDJfc3NoX2JhY2sucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX21scC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3RlbXBfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl90ZW1wX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gc2FsaW5pdHlfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9jaGxfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX2NobF9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9vMl9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9vMl9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCkFuZCBub3cgMjAxNF8wNg0KDQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJnbGlzdFsgLGMoImxvbmdpdHVkZV8iLCJsYXRpdHVkZV9tIildICMgVGhpcyBpcyB0byB0ZWxsIFIgd2hlcmUgdGhlIGNvb3JkaW5hdGVzIGFyZS4gTm90ZSB0aGF0IHRoZSBjb2x1bW4gb3JkZXIgbmVlZHMgdG8gYmUgbG9uZ2l0dWRlLCBsYXRpdHVkZQ0KdGVzdGJnbGlzdHNwIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSB0ZXN0YmdsaXN0LCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBUUlVFKSAjdHJ1ZSBtZWFucyB0aGUgZnVsbCBwYXRoIGlzIGluY2x1ZGVkDQpub19uZXRjZGYgPC0gbGVuZ3RoKG5ldGNkZl9saXN0KSAjZm9yIHRoZSBsb29wIC0gbmVlZCB0byBrbm93IGhvdyBtYW55IGZpbGVzIHRvIGN5Y2xlIHRocm91Z2gNCm5ldGNkZl9uYW1lIDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvZW52L2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBGQUxTRSkgI2ZhbHNlIG1lYW5zIHRoZSBwYXRoIGlzIG5vdCBpbmNsdWRlZA0KYWVhIDwtIHJhc3RlcigiLi4vb3V0cHV0L2Vudi9hZWEudGlmIikgDQp5ciA8LSAyMDE0ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiB5ZWFyDQptdGggPC0gMDYgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIG1vbnRoDQoNCmZvciAoaSBpbiAxOm5vX25ldGNkZikgeyAgDQogIHByaW50KG5ldGNkZl9uYW1lW2ldKSAjdGhpcyBqdXN0IHByaW50cyB0aGUgbmFtZSBvZiB0aGUgbmV0Q0RGIFIgaXMgd29ya2luZyBvbmUNCiAgYnJreXIgPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDEpKSAjIGV4dHJhY3RpbmcgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIHllYXIpDQogIGJya210aCA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMikpICMgZXh0cmFjdGluZyB0aGUgc2Vjb25kIHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIG1vbnRoKQ0KICBicmt2YXIgPC0gKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMykpICMgZXh0cmFjdGluZyB0aGUgdGhpcmQgcGFydCBvZiB0aGUgbmV0Y2RmIChpbmMubmMpDQogIHRlbXBfYnJpY2sgPC0gYnJpY2sobmV0Y2RmX2xpc3RbaV0sIGx2YXIgPSA0KQ0KICB0ZW1wX2JyaWNrIDwtIHByb2plY3RSYXN0ZXIodGVtcF9icmljaywgYWVhKSANCiAgICBmb3IgKGogaW4gMTpucm93KHRlc3RiZ2xpc3RzcCkpIHsgIA0KICAgICAgZGUgPC0gdGVzdGJnbGlzdHNwJGRlcHRobGF5ZXJub1tbal1dICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBkZXB0aCBsYXllcg0KICAgICAgICAgIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInRlbXAubmMiKXsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNhbGluaXR5Lm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gImNobC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJvMi5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJtbHAubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRtbHBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNzaC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNzaF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICANCiAgICAgICAgICB9DQogICAgIA0KICAgIH0NCn0NCndyaXRlLmNzdih0ZXN0YmdsaXN0c3AsICIuLi9kYXRhL2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9hbGxiYWNrZ3JvdW5kcG9pbnRzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KdGVzdF9iYWNrX2RmIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJnbGlzdHNwKQ0KcHJpbnQoU3lzLnRpbWUoKS1zdHJ0KSAjdGltZSBpdCB0b29rIHRvIHJ1bg0KYGBgDQpvayBub3cgY3JlYXRlIHRoZSBmaXJzdCBsb3Qgb2YgcmFuZG9tIGZvciAyMDE0XzA2DQoNCmBgYHtyfQ0KdGVzdGJrMTAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMCksIF0gICN3aGVyZSAxMDAwMCA9IG51bWJlciBvZiByb3dzIHRvIHNhbXBsZSAobGFyZ2Ugc2FtcGxlIGFzIHBlciBtYXhlbnQpDQp0ZXN0YmsyMDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDIwMDAwKSwgXSAgDQp0ZXN0YmszMDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDMwMDAwKSwgXSAgDQp0ZXN0Yms1MDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDUwMDAwKSwgXSAgDQp0ZXN0YmsxMDAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMDApLCBdICANCnRlc3RiazE5MDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDE5MDAwMCksIF0gIA0KYGBgDQoNCmFuZCBwbG90DQoNCg0KYGBge3J9DQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHNzaF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X3NzaC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBtbHBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9tbHAucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gdGVtcF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X3RlbXBfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X3RlbXBfZGVwdGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gc2FsaW5pdHlfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zYWxpbml0eV9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHNhbGluaXR5X2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X3NhbGluaXR5X2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X2NobF9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IGNobF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9jaGxfZGVwdGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gbzJfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9vMl9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAxNDA2X28yX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCg0KDQojIDNkIHBsb3QgYmFja2dyb3VuZCBwb2ludHMNCg0KYGBge3J9DQpiY2syMDE0XzA2XzNkIDwtIHBsb3RfbHkoeD0gdGVzdGJrMTAwMDAyMDE0JGxvbmdpdHVkZV8sIHkgPSB0ZXN0YmsxMDAwMDIwMTQkbGF0aXR1ZGVfbSwgeiA9IHRlc3RiazEwMDAwMjAxNCRkZXB0aGxheWVybm8pDQpiY2syMDE0XzA2XzNkDQpgYGANCg0KIyAyZCBwbG90IGJhY2tncm91bmQgcG9pbnRzDQoNCmBgYHtyfQ0KYmNrMjAxNF8wNl8yZCA8LSBwbG90KHg9IHRlc3RiazEwMDAwMjAxNCRsb25naXR1ZGVfLCB5ID0gdGVzdGJrMTAwMDAyMDE0JGxhdGl0dWRlX20pDQpkZXYuY29weShwbmcsIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svYmNrMTAwMDBfMmQucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmBgYA==